home *** CD-ROM | disk | FTP | other *** search
/ MacFormat España 15 / macformat_15.iso / Shareware Internet / Desarrolladores / gray image 2.1 / read_def.cc < prev    next >
Text File  |  1995-07-30  |  14KB  |  445 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Grayscale Image
  6.  *
  7.  *        Read an image in the Data Exchange Format
  8.  *
  9.  * which is used to exchange SAT imagery and other weather products
  10.  * within the weather community.
  11.  * The DEF format is a tagged format described in the document
  12.  *    Standard Formats for Weather Data Exchange Among Automated
  13.  *    Weather Information Systems
  14.  *    OFCM / Office of the Federal Coordinator for Meteorological
  15.  *    Services and Supporting Research
  16.  *    U.S. Department of Commerce / National Oceanic and Atmospheric
  17.  *    Administration,
  18.  *    FCM-S2-1990, Washington, D.C., May 1990
  19.  *
  20.  * In short, a DEF file consits of a sequence of fields. Each field is a
  21.  * collection of two-byte words. The order of bytes within a word is
  22.  * bigendian (the most significant byte first). A field starts with a
  23.  * standard header that specifies the total field length and the
  24.  * field type (mode/submode). The header is followed by data
  25.  * which meaning depends on the field type as determined by a
  26.  * particular mode/submode. The data may be followed by a checksum.
  27.  * Control fields describe the product, conditions in which it was
  28.  * acquired, and other relevant information. Data fields contain data
  29.  * of the product, say, raster scans of a satellite image.
  30.  *
  31.  * As far as SAT product are concerned, the following sequence of fields
  32.  * is expected within the DEF file
  33.  *    Product ID field, mode 1/submode 1
  34.  *    Product Def block, mode 6/submode 020
  35.  *               [mode 1/submode 5]      (field/data widths specs)
  36.  *               [mode 1/submode 3]      (Additional secrecy info)
  37.  *               [mode 6 submode 030]      (pixel product def)
  38.  *    Data descr block sets
  39.  *               mode 6/submode 1      (describing raster scans)
  40.  *    End Of Product block, mode 1/submode 2
  41.  *
  42.  * $Id: read_def.cc,v 1.2 1995/03/09 15:48:16 oleg Exp oleg $
  43.  *
  44.  ************************************************************************
  45.  */
  46.  
  47. #include "image.h"
  48. #include "endian_io.h"
  49.  
  50.                 // A 2-byte integer with the guaranteed
  51.                 // "Most-significant-byte-first" byte
  52.                 // order
  53. class Word
  54. {
  55.   unsigned char byte1, byte2;
  56. public:
  57.                     // Convert to a regular int
  58.   operator unsigned short (void) const
  59.         { return ((unsigned short)byte1 << 8) | byte2; }
  60.   operator short (void) const { return ((short)byte1 << 8) | byte2; }
  61. };
  62.  
  63. class DEFTag            // A DEF field tag
  64. {
  65.   char mode;                // a combination of mode and submode
  66.   char submode;                // codes
  67.  
  68. public:
  69.   DEFTag(void) { mode = submode = 0; }
  70.   DEFTag(char _mode, char _submode) : mode(_mode), submode(_submode) {}
  71.   DEFTag& operator = (const unsigned short word)
  72.     { mode = (word >> 8) & 0xff; submode = word & 0xff; }
  73.   bool operator == (const DEFTag& a_tag) 
  74.     { return *(unsigned short *)this == *(unsigned short *)&a_tag; }
  75.   operator const char * (void) const;    // Give a string representation
  76. };
  77.  
  78.                 // Give a string representation for a class
  79.                 // Returns a ptr to a STATIC string
  80. DEFTag::operator const char * (void) const
  81. {
  82.   static char buff[40];
  83.   sprintf(buff,"mode %0o, submode %0o",mode,submode);
  84.   return buff;
  85. }
  86.  
  87.                 // DEF file is a collection of tagged field
  88.                 // Here is a generic field
  89. class Field : public DEFTag
  90. {
  91.   friend class StdField;            // Standard Field header
  92.  
  93.   short data_size;        // Actual size of the DATA, bytes 
  94.   Word data[2048];        // A data part of the field
  95.  
  96. public:
  97.   Field(void) : data_size(0) {}        // Create an "empty" field
  98.   friend EndianIn& operator >> (EndianIn& fs, Field& field);
  99.   int length(void) const    { return data_size; }
  100. };
  101.  
  102.                 // Read in a field from the file
  103. EndianIn& operator >> (EndianIn& fs, Field& field)
  104. {
  105.   unsigned short word = fs.read_short("Reading the 1st word of the field");
  106.   bool checksum_present = false;
  107.   unsigned short checksum = 0;
  108.  
  109.   int length_words = 0;                // Data size in words
  110.   if( (word & 0xc000) == 0 )
  111.     checksum_present = true,
  112.     length_words = (word & ~0xc000) - 1 - 1 -1;    // length, mode, and cs words
  113.   else if( (word & 0xc000) == 0x4000 )
  114.     checksum_present = false,
  115.     length_words = (word & ~0xc000) - 1 - 1;    // 1 word length, 1 word mode
  116.   else if( (word & 0xc000) == 0xc000 )
  117.     _error("Can't handle a field w/o a length");
  118.   else
  119.     _error("Invalid flag in the 1st field of a word %04X",word);
  120.  
  121.   field.data_size = length_words * sizeof(Word);
  122.  
  123.   if( checksum_present )
  124.     checksum = word;
  125.  
  126.   word = fs.read_short("Reading mode/submode");
  127.   if( checksum_present )
  128.     checksum += word;
  129.   *(DEFTag *)&field = word;
  130.  
  131.   assert( field.data_size >= 0 );
  132.   assert( field.data_size < sizeof(field.data) );
  133.  
  134.   if( !fs.read((char *)field.data,field.data_size) )
  135.     _error("Dying because of I/O error above",
  136.        (perror("Field data read error"),0));
  137.  
  138.   if( checksum_present )
  139.   {
  140.     register Word * dp;
  141.     for(dp=field.data; dp < field.data + length_words;)
  142.       checksum += (unsigned short)*dp++;
  143.     checksum += fs.read_short("reading the checksum");
  144.     assert( checksum == 0 );
  145.   }
  146.  
  147.   return fs;
  148. }
  149.  
  150.  
  151.                 // Standard Field header, from which
  152.                 // particular product field inherit
  153. class StdField : public DEFTag
  154. {
  155. public:
  156.   const enum Length_type { Exact_length, Min_length };
  157. private:
  158.   const int length_words;        // Length of the field in words
  159.   Length_type length_type;
  160.   char data[0];                // Data follow immediately after
  161. protected:
  162.   StdField(const DEFTag tag, const int _length, const Length_type _ltype)
  163.     : DEFTag(tag), length_words(_length), length_type(_ltype) {}
  164.   void operator = (const Field& field);
  165.   void load_from(const Field& field);
  166. };
  167.  
  168.                 // Assignment of a field
  169. void StdField::load_from(const Field& field)
  170. {
  171.   assert( *(DEFTag *)this == field );    // Make sure the field assigned is 
  172.                     // really of the type we expect
  173.   if( length_type == Exact_length )
  174.     assert( sizeof(Word) * length_words == field.length() );
  175.   else
  176.     assert( sizeof(Word) * length_words <= field.length() );
  177.   memcpy(data,field.data,field.length());
  178. }
  179.  
  180. /*
  181.  *------------------------------------------------------------------------
  182.  *              Specific blocks for SAT products
  183.  * Constructor assignes default values to be used if the field isn't
  184.  * specified in the input stream
  185.  */
  186.  
  187. class ProductIDField : public StdField
  188. {
  189.                 // Contents of the data field
  190.   char originator[4];            // Facility that has generated product
  191.   char classification;            // secrecy stuff
  192.   char retention_time;            // in days, -1 or 0 means dummy
  193.   char file_indicator;            // Code of the originating agency
  194.   char catalog_no[4];
  195.   char time_generated[3];        // e.g., in hrs
  196.   char misc_id[2];            // See App. C, Table C2-1
  197.                     // Time the file was generated 
  198.   Word year;                // full century year, in binary
  199.   char month, day, hour, minute;
  200.  
  201. public:
  202.   ProductIDField(const Field& field);
  203.   operator const char * (void) const;    // Give a readable description
  204. };
  205.  
  206.                 // Assign from a generic field
  207. ProductIDField::ProductIDField(const Field& field)
  208.     : StdField(DEFTag(1,1),11,StdField::Exact_length)
  209. {
  210.   load_from(field);
  211. }
  212.  
  213.                 // Give a readable description of the Product
  214.                 // ID. Returns a ptr to a STATIC string
  215. ProductIDField::operator const char * (void) const
  216. {
  217.   static char buffer[700];
  218.   sprintf(buffer,"Originator %.4s, classification %c, retention_time %d\n"
  219.       "file_indicator %0o, catalog_number %.4s, time_generated %.3s\n"
  220.       "misc id %.2s, date %d/%d/%d %02d:%02d\n",
  221.       originator,classification, 
  222.       (retention_time == -1 ? 0 : retention_time),
  223.       file_indicator,catalog_no,time_generated,misc_id,
  224.       month,day,(unsigned short)year,hour,minute);
  225.   return buffer;
  226. }
  227.  
  228.                 // Classification Block
  229. class ClassifField : public StdField
  230. {
  231.   char title[100];
  232. public:
  233.   ClassifField(void)  
  234.     : StdField(DEFTag(1,3),0,StdField::Min_length) { title[0] = '\0'; }
  235.   void operator = (const Field& field);
  236.   void print(void) const;
  237. };
  238.  
  239. void ClassifField::operator = (const Field& field)
  240. {
  241.   load_from(field);
  242.   assert( field.length() < sizeof(title)-1 );
  243.   title[field.length()] = '\0';
  244. }
  245.  
  246. void ClassifField::print(void) const
  247. {
  248.   message("Classification %s\n",title);
  249. }
  250.  
  251.                 // Field describing bit sizes of other
  252.                 // field and their relative layouts
  253. class DFWidthField : public StdField 
  254. {
  255.   char field_width           : 7;
  256.   char cross_byte_boundaries   : 1;
  257.   char data_width           : 7;    // bits for the actual data
  258.   char left_justified           : 1;
  259.   DEFTag apply_to;            // Mode/submode for which applicable
  260.  
  261. public:
  262.   DFWidthField(void)
  263.     : StdField(DEFTag(1,5),2,StdField::Exact_length), apply_to(DEFTag(6,1))
  264.     { cross_byte_boundaries = left_justified = 0;
  265.       field_width = data_width = 8;
  266.     }
  267.   void operator = (const Field& field);
  268.   void print(void) const;
  269. };
  270.  
  271. void DFWidthField::operator = (const Field& field)
  272. {
  273.   load_from(field);
  274.   assert( field_width <= 16 && field_width > 0 );
  275.   assert( data_width <= field_width && data_width > 0 );
  276. }
  277.  
  278. void DFWidthField::print(void) const
  279. {
  280.   message("%d data bits within %d-bit field %s byte/word boundaries\n",
  281.       data_width,field_width,
  282.       cross_byte_boundaries ? "crossing" : "within");
  283.   message("%s, applied to tag %s\n",
  284.       left_justified ? "left_justified" : "contiguos",
  285.       (const char *)apply_to);
  286. }
  287.  
  288.  
  289.  
  290.                 // Satellite Product Definition Block
  291. class SATDefField : public StdField
  292. {
  293. public:
  294.   char pi_set;            // Background projection on which SAT is valid
  295.   char gi_set;            // Grid indicator for which the data is valid
  296.   char sat_id[2];
  297.   Word longit_X;        // Longitude X for the base of the product
  298.   char resolution_code;        // in 10s of nautical miles
  299.   char sat_type;        // 0 - visual, 1 - IR, mixed otherwise
  300.   Word x_max;            // no. of pixels across
  301.   Word y_max;            // no. of pixels in height
  302.   unsigned char enhance_max;    // Needed if pixel enhancement is used
  303.   unsigned char enhance_min;    // (limits of the gray-scale look-up referenced
  304.   char enhance_id;        // by the enhance_id)     
  305.   unsigned char arc_length;    // Length of each scanline in tens of minutes
  306.                 // of arc
  307.   char x_center, y_center;    // Center of the product in units of the grid
  308.   Word latitude;        // LAT and LON of the center of the product in
  309.   Word longitude;        // hundredths of degree
  310.   unsigned char title_len;
  311.   char title[256];
  312.   
  313. public:
  314.   SATDefField(const Field& field);
  315.   void print(void) const;
  316. };
  317.  
  318. SATDefField::SATDefField(const Field& field)
  319.     : StdField(DEFTag(6,020),13,StdField::Min_length)
  320. {
  321.   load_from(field);
  322.   title[title_len] = '\0';
  323. }
  324.  
  325.  
  326. void SATDefField::print(void) const
  327. {
  328.   message("\nSAT image '%s' id %.2s type %d\n",title,sat_id,sat_type);
  329.   message("%dx%d pixels, enhancement code %d, for pixel interval %d-%d\n",
  330.       (unsigned short)x_max,(unsigned short)y_max, enhance_id,
  331.       enhance_min,enhance_max);
  332.   message("Background projection %d, grid %d, base longitude %d\n",
  333.       pi_set,gi_set, (short)longit_X);
  334.   message("scanline resolution %f nautical miles, or %d' of grid\n",
  335.       resolution_code/10.,10*arc_length);
  336.   message("Image center is at (%d,%d) on the grid, or %2.2f LAT %2.2f LONG\n",
  337.       x_center,y_center,((short)latitude)/100.,((short)longitude)/100.);
  338. }
  339.  
  340.                 // Pixel product definition block
  341. class PixelDefField : public StdField 
  342. {
  343.   char pi_set;        // Define the background projection for the product
  344.   char matrix_code;    // Code for standard SAT dimensions
  345.   char scan_code;    // Raster scan directions (1 - from top to bottom)
  346.   char pack_code;    // Pixel pack code
  347.  
  348. public:
  349.   PixelDefField(void)
  350.     : StdField(DEFTag(6,030),2,StdField::Exact_length)
  351.     { pi_set = 0; matrix_code = -1; scan_code = 1; pack_code = 0; }
  352.   void operator = (const Field& field);
  353.   void print(void) const;
  354. };
  355.  
  356. void PixelDefField::operator = (const Field& field)
  357. {
  358.   load_from(field);
  359.   assert( matrix_code < 64 );
  360.   assert( scan_code > 0 && scan_code <= 2 );
  361. }
  362.  
  363. void PixelDefField::print(void) const
  364. {
  365.   message("\nbackground grid id %d, pixel matrix code %d\n",
  366.       pi_set,matrix_code);
  367.   message("scanlines go %s packed with method labelled %d\n",
  368.       scan_code == 1 ? "top to bottom" : "bottom to top",
  369.       pack_code);
  370. }
  371.  
  372.  
  373.                 // Pixel product definition block
  374. class RasterScanField : public StdField 
  375. {
  376. public:
  377.   Word xrow, ycol;    // Coordinates of the beginning of a scanline
  378.   Word no_pixels;    // in this raster line
  379.   unsigned char pixels [4096];    // Pixels themselves
  380.  
  381. public:
  382.   RasterScanField(void)
  383.     : StdField(DEFTag(6,1),3,StdField::Min_length)
  384.     { *(short *)&xrow = 0; *(short *)&ycol = 0; *(short *)&no_pixels = 0; }
  385.   void operator = (const Field& field);
  386. };
  387.  
  388.  
  389. void RasterScanField::operator = (const Field& field)
  390. {
  391.   load_from(field);
  392. }
  393.  
  394. main(void)
  395. {
  396.   EndianIn fs("/projects/r2d2/oleg/IMAGES/packed.700");
  397.   fs.set_bigendian();
  398.   Field field;
  399.  
  400.   fs >> field;
  401.   ProductIDField pid(field);
  402.   message((const char *)pid);
  403.  
  404.   fs >> field;
  405.   SATDefField sat_def(field);
  406.   sat_def.print();
  407.  
  408.   RasterScanField scanline;
  409.  
  410.   PixelDefField pixel_def;    // Other fields that might show up
  411.   ClassifField secrecy_fld;
  412.   DFWidthField width_def;
  413.  
  414.   for(fs >> field; !(field == scanline); fs >> field)
  415.   {
  416.     if( field == pixel_def )
  417.       pixel_def = field, pixel_def.print();
  418.     else if( field == secrecy_fld )
  419.       secrecy_fld = field, secrecy_fld.print();
  420.     else if( field == width_def )
  421.       width_def = field, width_def.print();
  422.     else
  423.       _error("Unexpected tag %s",(const char *)*(DEFTag *)&field);
  424.   }
  425.  
  426.                 // Check out that we can handle that image
  427.  
  428.   IMAGE image((unsigned short)sat_def.y_max,
  429.           (unsigned short)sat_def.x_max,8);
  430.  
  431.   for(; !(field == DEFTag(1,2)); fs >> field)
  432.   {
  433.     scanline = field;
  434.     register int i;
  435. //    message("xrow %d, ycol %d, %d pixels\n",(unsigned short)scanline.xrow,
  436. //        (unsigned short)scanline.ycol,(unsigned short)scanline.no_pixels);
  437.     for(i=0; i<(unsigned short)scanline.no_pixels; i++)
  438.       image((unsigned short)scanline.xrow,(unsigned short)scanline.ycol+i)
  439.     = scanline.pixels[i];
  440.   }
  441.   image.display("image");
  442. }
  443.  
  444.  
  445.